package com.xiaoyun.xpath;

import cn.wanghaomiao.xpath.model.JXDocument;
import com.xiaoyun.xpath.handler.annotation.Xpath;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.*;

public abstract class AbstractXpathHandler implements XpathHandler {

//    public static final int CORE_SIZE = Runtime.getRuntime().availableProcessors();
//
//    public static final int MAX_SIZE = CORE_SIZE * 2;
//
//    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_SIZE, MAX_SIZE, 10, TimeUnit.SECONDS,
//            new LinkedBlockingDeque<>(100000),
//            Executors.defaultThreadFactory(),
//            new ThreadPoolExecutor.AbortPolicy());


    @Override
    public <T> T handler(String body, Class<T> clazz) {
        return this.handler(body, clazz, null);
    }


    @Override
    public <T> T handler(String body, Class<T> clazz, Map<String, String> mappingMap) {
        if (body == null) {
            return null;
        }

        Field[] fields = clazz.getDeclaredFields();
        boolean flag = false;
        for (Field field : fields) {
            //判断class中是否包含 xpath注解
            if (field.getAnnotation(Xpath.class) != null) {
                flag = true;
                break;
            }
        }
        //当 class中不包含 xpath注解 或者 map中也没有映射 ,直接返回null 不做处理
        if (!(HandlerUtils.isNotNullMap(mappingMap) || flag)) {
            return null;
        }
        JXDocument jxDocument = new JXDocument(body);
        T t = null;
        try {
            t = getT(clazz);
            for (Field field : clazz.getDeclaredFields()) {
                Type type = field.getAnnotatedType().getType();
                String typeName = type.getTypeName();

                //根据不同属性 来执行各自的方法
                typeNameBuild(typeName, clazz, jxDocument, t, mappingMap, field);
                //多线程异步执行
//                CompletableFuture.runAsync(new FieldTask(typeName, clazz, jxDocument, t, mappingMap, field), executor);
//                executor.submit(new FieldTask(typeName, clazz, jxDocument, t, mappingMap, field));

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

    protected <T> T getT(Class<T> clazz) throws InstantiationException, IllegalAccessException, java.lang.reflect.InvocationTargetException, NoSuchMethodException {
        return clazz.getDeclaredConstructor().newInstance();
    }

    protected abstract <T> void typeNameBuild(String typeName, Class<T> clazz, JXDocument jxDocument, T t, Map<String, String> mappingMap, Field field) throws Exception;

}
